<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Schedule;
use App\Models\Attendance;
use Illuminate\Http\Request;
use App\Models\System\SysLog;
use App\Package\Attendance\Days;
use Illuminate\Support\Facades\DB;
use App\Models\Attendance\Integral;
use Illuminate\Support\Facades\Auth;
use App\Exports\AttendanceReportExport;
use Illuminate\Database\Query\JoinClause;
use App\Repositories\AttendanceRepository;
use App\Http\Requests\Logic\Attendance\ReportOfDay;
use App\Http\Requests\Logic\Attendance\ReportOfYear;
use App\Models\Statistical\MonthlyAttendanceReports;
use App\Http\Requests\Logic\Attendance\ReportOfMonth;
use App\Http\Requests\Logic\Attendance\QueryResource;
use App\Http\Requests\Logic\Attendance\StoreResource;
use App\Http\Requests\Logic\Attendance\UpdateResource;
use App\Http\Requests\Logic\Attendance\SummaryOfMonth;
use App\Http\Requests\Logic\Attendance\QueryCollection;
use App\Http\Requests\Logic\Attendance\DestroyResource;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * 考勤模块控制器
 *
 * Date: 12/04/2018
 * @author George
 * @package App\Http\Controllers
 */
class AttendanceController extends Controller
{
	protected $attendanceRepository;

	/**
	 * AttendanceController constructor.
	 * @param AttendanceRepository $attendanceRepository
	 */
	public function __construct(AttendanceRepository $attendanceRepository)
	{
		$this->attendanceRepository = $attendanceRepository;
	}

	/**
	 * 获取考勤信息
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @param QueryCollection $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function index(QueryCollection $request)
	{
		$user = $request->user();
		$start = $request->get('start');
		$end = $request->get('end');
		$type = $request->get('type');
		$status = $request->get('status');
		$genre_id = $request->get('genre_id');
		$project_id = $request->get('project_id');
		$paginate = $request->get('paginate');

		$query = Attendance::query()->with('user:id,name', 'genre:id,name', 'project:id,name')->where('company_id', $user->company_id);

		if ($start && $end) {
			$query->whereBetween('checkin_time', [$start, $end]);
		}

		if ($status) {
			$query->where('checkin_status', $status)
				->orWhere('checkout_status', $status);
		}

		if ($genre_id) {
			$query->where('genre_id', $genre_id);
		}

		if ($type) {
			$query->where('type', $type);
		}

		if ($project_id) {
			$query->where('project_id', $project_id);
		}

		return success($query->orderByDesc('checkin_time')->paginate($paginate));
	}

	/**
	 * 获取考勤数据详情
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @param QueryResource $request
	 * @param Attendance $attendance
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function show(QueryResource $request, Attendance $attendance)
	{
		return success($attendance);
	}

	/**
	 * 创建考勤记录
	 *
	 * Date: 17/04/2018
	 * @author George
	 * @param StoreResource $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function store(StoreResource $request)
	{
		$attributes = $request->all();
		$attendance = $this->attendanceRepository->createOrUpdate($attributes);
		return success($attendance);
	}

	/**
	 * Date: 2018/6/29
	 * @author George
	 * @param UpdateResource $request
	 * @param Attendance $attendance
	 */
	public function update(UpdateResource $request, Attendance $attendance)
	{
		// Todo 业务逻辑待定
	}

	/**
	 * Date: 2018/6/29
	 * @author George
	 * @param DestroyResource $request
	 */
	public function destroy(DestroyResource $request)
	{
		// Todo 业务逻辑待定
	}

	/**
	 * 获取指定用户单日的考勤详情信息
	 *
	 * Date: 2018/6/22
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function detailOfDay(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'user_id' => 'required',
			'date' => 'nullable',
		], [
			'project_id.required' => '请选择项目',
			'user_id.required' => '用户信息有误',
		]);

		$project_id = $request->get('project_id');
		$user_id = $request->get('user_id');
		$date = $request->get('date', date('Y-m-d'));

		$attendance = Attendance::with('genre:id,start,end')->where([
			['project_id', '=', $project_id],
			['user_id', '=', $user_id]
		])->whereDate('checkin_time', $date)->first();

		return success($attendance);
	}

	/**
	 * 获取考勤月报详情
	 *
	 * Date: 2018/6/29
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function detailOfMonth(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'month' => 'nullable',
		]);
		$project_id = $request->get('project_id');
		$string = $request->get('month', date('Y-m'));
		$start = $string . '-01';
		$end = date('Y-m-t', strtotime($string));

		// TODO 节假日查询巡逻
		$holiday = 0;

		$users = DB::table('users')
			->selectRaw('users.id as user_id,users.name as user_name,users.avatar,cast(sum(score) as signed) as total,count(attendances.user_id) as attendance_count')
			->leftJoin('integrals', function ($join) use ($start, $end) {
				/**
				 * @var JoinClause $join
				 */
				$join->on('users.id', '=', 'integrals.user_id')->whereBetween('date', [$start, $end]);
			})
			->leftJoin('attendances', function ($join) use ($start, $end) {
				/**
				 * @var JoinClause $join
				 */
				$join->on('integrals.user_id', '=', 'attendances.user_id')->whereBetween('checkin_time', [$start, $end]);
			})
			->where('integrals.project_id', $project_id)
			->groupBy('integrals.user_id')
			->orderByDesc('total')
			->get()->map(function ($user) use ($start, $end, $holiday) {
				$schedules = DB::table('schedules')
					->select(['genre_id', 'genre_name'])
					->where('user_id', $user->user_id)
					->whereBetween('date', [$start, $end])
					->get();
				if ($schedules->count() > 0) {
					$genres = $schedules->groupBy('genre_name')->toArray();
					$user->genres = [];
					foreach ($genres as $name => $genre) {
						$user->genres[] = [
							'name' => $name,
							'count' => count($genre)
						];
					}
				}

				$user->genres[] = [
					'name' => '休息日',
					'count' => Days::all($start, $end)->days - $schedules->count() - $holiday
				];

				$user->genres[] = [
					'name' => '法定假日',
					'count' => $holiday
				];
				return $user;
			});

		return success($users);
	}

	/**
	 * 获取项目考勤日报
	 *
	 * Date: 2018/6/19
	 * @author George
	 * @param ReportOfDay $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function reportOfDay(ReportOfDay $request)
	{
		$user = Auth::user();
		$project_id = $request->get('project_id');
		$date = $request->get('date', date("Y-m-d"));
		// 判断是否拥有某个项目距
		if (!$user->hasProject($project_id)) {
			return failed('您无权访问', 403);
		}
		$schedules = Schedule::query()->select(['id', 'project_id', 'genre_id', 'demand_id', 'user_id'])
			->where('project_id', $project_id)
			->whereDate('date', $date)
			->with(['attendance', 'genre'])
			->get();

		$report = [
			'date' => $date,
			'tardy' => 0,
			'early' => 0,
			'absenteeism' => 0,
			'nsignout' => 0,
			'legwork' => 0,
			'should_count' => $schedules->count(),
			'attendanced_count' => 0
		];

		$genres = DB::table('genres')->where('project_id', $project_id)->select(['id', 'name', 'start', 'end'])->get();

		// 遍历获取考勤状态汇总数据
		$schedules->map(function ($schedule) use ($report, $genres) {
			// 判断是否存在考勤记录
			if ($schedule->attendance) {
				switch ($schedule->attendance->checkin_status) {
					case 'tardy':
						$report['tardy'] += 1;
						break;
					case 'absenteeism':
						$report['absenteeism'] += 1;
						break;
					case 'legwork':
						$report['legwork'] += 1;
						break;
					default:
						break;
				}

				switch ($schedule->attendance->checkout_status) {
					case 'early':
						$report['early'] += 1;
						break;
					case null:
						$report['nsignout'] += 1;
						break;
					default:
						break;
				}

				// 统计出勤人数
				$report['attendanced_count'] =+ 1;
			}

			foreach ($genres as $key => $genre) {
				// 判断排班的班次ID是否存在
				if ($schedule->genre_id == $genre->id) {
					array_has($genres[$key], 'should_count') ? $genres[$key]->should_count += 1 : $genres[$key]->should_count = 1;
					array_has($genres[$key], 'attendanced_count') ? : $genres[$key]->attendanced_count = 0;

					if ($schedule->attendance) {
						$genres[$key]->attendanced_count += 1;
						$genres[$key]->attendances[] = $schedule->attendance;
					}
				} else {
					$genres[$key]->attendances = [];
					$genres[$key]->should_count = 0;
					$genres[$key]->attendanced_count = 0;
				}
			}
		});

		$report['genres'] = $genres;

		return success($report);
	}

	/**
	 * 获取项目考勤月报
	 *
	 * Date: 2018/6/25
	 * @author George
	 * @param ReportOfMonth $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function reportOfMonth(ReportOfMonth $request)
	{
		$string = $request->get('month', date('Y-m'));
		$year = substr($string, 0, 4);
		$month = substr($string, 5, 2);
		$project_id = $request->get('project_id');
		$user = Auth::user();

		$report = [
			'month' => $string,
			'tardy' => 0,
			'early' => 0,
			'absenteeism' => 0,
			'nsignout' => 0,
			'legwork' => 0,
			'should_count' => Schedule::query()->whereYear('date', $year)->whereMonth('date', $month)->where('project_id', $project_id)->count(),
			'attendanced_count' => 0
		];

		Attendance::query()
			->where('project_id', $project_id)
			->whereYear('checkin_time', $year)
			->whereMonth('checkin_time', $month)
			->chunk(100, function ($records) use (&$report) {
				foreach ($records as $record) {
					switch ($record->checkin_status) {
						case 'tardy':
							$report['tardy'] += 1;
							break;
						case 'absenteeism':
							$report['absenteeism'] += 1;
							break;
						case 'legwork':
							$report['legwork'] += 1;
							break;
					}

					switch ($record->checkout_status) {
						case 'early':
							$report['early'] += 1;
							break;
						case 'nsignout':
							$report['nsignout'] += 1;
							break;
					}
					$report['attendanced_count'] += 1;
				}
			});

		$report['abnormal_rate'] = round(($report['tardy'] + $report['early'] + $report['absenteeism'] + $report['nsignout']) / $report['should_count'] * 100, 2);

		$report['departure_count'] =  DB::table('company_user_pivot')
			->whereYear('departure_at', $year)
			->whereMonth('departure_at', $month)
			->where('company_id', $user->company_id)
			->count();
		$report['hire_count'] = DB::table('company_user_pivot')
			->whereYear('hiredate_at', $year)
			->whereMonth('hiredate_at', $month)
			->where('company_id', $user->company_id)
			->count();
		$report['staff_count'] = DB::table('users')
			->where('company_id', $user->company_id)
			->count();
		$report['departure_rate'] = round($report['departure_count'] / $report['staff_count'] * 100, 2);

		/**
		 * 获取前三名人员
		 */
		$scores = Integral::query()
			->whereYear('date', $year)
			->whereMonth('date', $month)
			->where('project_id', $project_id)
			->selectRaw('sum(score) as total,user_id')
			->groupBy('user_id')
			->take(3)
			->orderByDesc('total')
			->get()->map(function ($score) use ($year, $month, $project_id) {
				$user = User::query()->where('users.id', $score->user_id)
					->select(['users.id', 'users.name','users.avatar', 'positions.name as position_name'])
					->leftJoin('positions', 'users.position_id', '=','positions.id')
					->first();
				$score->name = $user->name;
				$score->avatar = $user->avatar;
				$score->position_name = $user->position_name;
				$score->attendance_count = DB::table('attendances')
					->whereYear('checkin_time', $year)
					->whereMonth('checkin_time', $month)
					->where('project_id', $project_id)
					->where('user_id', $user->id)
					->count();
				return $score;
			});

		$report['top'] = $scores->toArray();

		return success($report);
	}

	/**
	 * 获取个人月度汇总数据
	 *
	 * Date: 2018/6/25
	 * @author George
	 * @param SummaryOfMonth $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function summaryOfMonth(SummaryOfMonth $request)
	{
		$project_id = $request->get('project_id');
		$user_id = $request->get('user_id');
		$month = $request->get('month', date('Y-m'));
		$start = $month . '-01';
		$end = $month . '-' . date('t', strtotime($month));
		$schedules = DB::table('schedules')->select([
			'schedules.date',
			'genres.name',
			'attendances.checkin_status',
			'attendances.checkout_status',
			'attendances.time_difference'
		])
			->leftJoin('genres', 'schedules.genre_id', '=', 'genres.id')
			->leftJoin('attendances', 'schedules.id', '=', 'attendances.schedule_id')
			->where([
				['schedules.project_id', '=', $project_id],
				['schedules.user_id', '=', $user_id]
			])
			->whereBetween('schedules.date', [$start, $end])
			->get()->map(function ($schedule) use ($project_id, $user_id) {
				if ($schedule->checkin_status !== '' && $schedule->checkin_status !== null) {
					$schedule->status = $this->status($schedule->checkin_status);
				} elseif ($schedule->checkout_status !== '' && $schedule->checkin_status !== null) {
					$schedule->status = $this->status($schedule->checkout_status);
				} elseif ($schedule->checkin_status === null && $schedule->checkout_status === null) {
					$schedule->status = null;
				}

				unset($schedule->checkin_status);
				unset($schedule->checkout_status);

				// 判断考勤排名
				if ($schedule->time_difference > 0) {
					$count = DB::table('attendances')->where([
						['project_id', '=', $project_id],
						['user_id', '=', $user_id],
						['time_difference', '>', $schedule->time_difference]
					])->whereDate('checkin_time', $schedule->date)->count();

					if ($count === 0) {
						$schedule->top = true;
					}
				} else {
					$schedule->top = false;
				}
				unset($schedule->time_difference);
				return $schedule;
			});
		return success($schedules);
	}

	/**
	 * Date: 2018/6/25
	 * @author George
	 * @param $status
	 * @return string
	 */
	private function status($status) {
		switch ($status) {
			case 'tardy':
				return '迟';
				break;
			case 'early':
				return '早';
			case 'absenteeism':
				return '旷';
			case 'nsignout':
				return '未';
			case 'legwork':
				return '外';
		}
	}

	/**
	 * 按年获取每个月的信息
	 *
	 * Date: 2018/6/19
	 * @author George
	 * @param ReportOfYear $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function validityOfYear(ReportOfYear $request)
	{
		$project_id = $request->get('project_id');
		$year = $request->get('year', date('Y'));
		$user = Auth::user();
		// 判断是否拥有某个项目距
		if (!$user->hasProject($project_id)) {
			return failed('您无权访问', 403);
		}
		$result = DB::table('attendances')
			->where('project_id', $project_id)
			->whereYear('checkin_time', $year)
			->selectRaw("date_format(checkin_time, '%m') as month")
			->groupBy('month')
			->pluck('month')->toArray();

		$months = [];

		for ($month = 1; $month <= 12; $month ++) {
			$months[] = [
				'month' => $month . '月',
				'validity' => in_array(sprintf("%02d",$month), $result)
			];
		}

		return success($months);
	}

	/**
	 * 项目纬度考勤月报
	 *
	 * Date: 2018/7/3
	 * @author George
	 * @param Request $request
	 * @return AttendanceReportExport|\Illuminate\Http\JsonResponse
	 */
	public function export(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'month' => 'nullable',
			'export' => 'nullable'
		]);
		$project_id = $request->get('project_id');
		$date = $request->get('month', date('Y-m'));
		$year = substr($date, 0, 4);
		$month = substr($date, 5, 2);
		$export = $request->get('export');

		$query = MonthlyAttendanceReports::query()->where('project_id', $project_id);

		$query->where('year', $year)->where('month', $month);

		// 生成一个月的每一天和星期信息
		$dates = Days::all($date . '-01', date("Y-m-t", strtotime($date)), true)->collection->map(function ($date) {
			return [
				'day' => substr($date, 8, 2),
				'week' => Days::getWeek($date)
			];
		});

		$columns = array_pluck($dates, 'day');
		$columns = array_map(function ($column) {
			return 'day_' . $column;
		}, $columns);
		array_unshift($columns, 'user_name', 'position');

		/**
		 * 导出数据
		 */
		if ($export) {
			SysLog::log(Auth::user(),'考勤模块','导出月考勤报表数据');
			return new AttendanceReportExport($query);
//			Excel::create('attendances', function ($excel) use ($query) {
//				/**
//				 * @var LaravelExcelWriter $excel
//				 */
//				$excel->sheet('项目列表', function($sheet) use ($query) {
//					/**
//					 * 设置列宽度
//					 * @var LaravelExcelWorksheet $sheet
//					 */
//					$sheet->setWidth(array(
//						'A'     =>  5,
//						'B'     =>  20,
//						'C'     =>  40,
//						'D'     =>  8,
//					));
//
//					/**
//					 * 设置对其方式
//					 */
//					$sheet->cells('A:Z', function($cells) {
//						/**
//						 * @var CellWriter $cells
//						 */
//						$cells->setAlignment('center');
//					});
//
//					$sheet->fromArray($query->get()->map(function ($item) {
//						return [
//							'1'=> $item->id,
//							'2'=> $item->position,
//							'3'=> $item->user_name
//						];
//					})->toArray());
//
//					$sheet->fromArray($query->get()->map(function ($item) {
//						return [
//							'序号'=> $item->id,
//							'职务'=> $item->position,
//							'姓名'=> $item->user_name,
//							'01'=> $item->day_01,
//							'02'=> $item->day_02,
//							'03'=> $item->day_03,
//							'04'=> $item->day_04,
//							'05'=> $item->day_05,
//							'06'=> $item->day_06,
//							'07'=> $item->day_07,
//							'08'=> $item->day_08,
//							'09'=> $item->day_09,
//							'10'=> $item->day_10,
//							'11'=> $item->day_11,
//							'12'=> $item->day_12,
//							'13'=> $item->day_13,
//							'14'=> $item->day_14,
//							'15'=> $item->day_15,
//							'16'=> $item->day_16,
//							'17'=> $item->day_17,
//							'18'=> $item->day_18,
//							'19'=> $item->day_19,
//							'20'=> $item->day_20,
//							'21'=> $item->day_21,
//							'22'=> $item->day_22,
//							'23'=> $item->day_23,
//							'24'=> $item->day_24,
//							'25'=> $item->day_25,
//							'26'=> $item->day_26,
//							'27'=> $item->day_27,
//							'28'=> $item->day_28,
//							'29'=> $item->day_29,
//							'30'=> $item->day_30,
//							'31'=> $item->day_31,
//						];
//					}));
//				});
//			})->download('xlsx');
		}

		$response = [
			"project_name" => "滨江凯旋门项目",
			"year" => $year,
			"month" => $month,
			"genres" => DB::table('genres')->where('project_id', $project_id)->get(['code', 'name']),
			"summary" => ["出勤", "培训", "总工时", "确认签字"],
			"dates" => $dates,
			"records" => $query->get($columns)
		];

		return success($response);
	}
}
